package com.abe.mvp.model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import com.abe.mvp.contact.SocketContact;
import com.abe.threadmill.R;
import com.abe.utils.NormalUtils;
import com.abe.utils.ThreadPoolUtils;

public class SocketModelImp implements SocketContact.Model {
	private static SocketModelImp socketModelImp;
	private static ISocketBack socketBack;
	public static final String bm = "utf-8"; // 全局定义，以适应系统其他部分
	/** code标识 */
	/** 错误 */
	public static final int CODE_ERROR = 0x001;
	/** 串口开启成功 */
	public static final int CODE_OPEN_SUCCESS = 0x002;
	/** 串口开启失败 */
	public static final int CODE_CLOSE_SUCCESS = 0x003;
	/** 下发命令成功 */
	public static final int CODE_SEND_DATA_SUCCESS = 0x004;
	/** 数据接收成功 */
	public static final int CODE_RECEIVE_DATA_SUCCESS = 0x005;
	/** 数据通道 */
	private Socket socket;
	private OutputStream mOutputStream;
	private InputStream mInputStream;
	private BufferedReader in = null;
	private PrintWriter out = null;
	/** 操作线程 */
	private ReadThread mReadThread;
	private MyTimeThread timer;
	private ConnectThread conn;

	private String IP;
	private int Port;
	/** 状态 */
	private boolean is_run;

	private SocketModelImp() {
	}

	/**
	 * @param callback
	 * @return SocketModelImp
	 */
	public static SocketModelImp from(ISocketBack callback) {
		socketBack = callback;
		if (socketModelImp == null) {
			synchronized (SocketModelImp.class) {
				if (socketModelImp == null)
					socketModelImp = new SocketModelImp();
			}
		}
		return socketModelImp;
	}

	@Override
	public void openSocket(String IP, int Port) {
		if (socket == null || socket.isClosed()) {
			is_run = true;
			try {
				this.IP = IP;
				this.Port = Port;
				conn = new ConnectThread(IP, Port);
				conn.start();
			} catch (Exception e) {
				socketBack.onResult(CODE_ERROR, null,
						NormalUtils.getString(R.string.socket_open_error));
			}
		}
	}

	@Override
	public void sendSocketCommand(String msg) {
		if (out != null) {
			if (msg != null) {
				try {
					out.print(msg);
					out.flush();
					socketBack.onResult(CODE_SEND_DATA_SUCCESS, null, null);
				} catch (Exception e) {
					e.printStackTrace();
					socketBack.onResult(CODE_ERROR, null,
							NormalUtils.getString(R.string.socket_send_error));
				}
			} else {
				socketBack.onResult(CODE_ERROR, null, "Command msg null");
			}
		} else {
			socketBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.socket_open_error));
		}
	}

	@Override
	public void checkScoket() {
		if (is_run) {
			ThreadPoolUtils.execute(new ConnectStatus());
		}
	}

	@Override
	public void closeSocket() {
		is_run = false;
		if (mReadThread != null) {
			mReadThread.interrupt();
		}

		try {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
			if (mInputStream != null) {
				mInputStream.close();
			}
			if (mOutputStream != null) {
				mOutputStream.close();
			}
			if (socket != null) {
				socket.close();
				socket = null;
				/** 串口关闭成功 */
				socketBack.onResult(CODE_CLOSE_SUCCESS, null, null);
			} else {
				/** 关闭成功 */
				socketBack.onResult(CODE_CLOSE_SUCCESS, null, null);
			}

		} catch (IOException e) {
			e.printStackTrace();
			socketBack.onResult(CODE_ERROR, null,
					NormalUtils.getString(R.string.socket_close_error));
		}

	}

	/** 连接线程 */
	class ConnectThread extends Thread {
		/** 配置 */
		private String IP;
		private int Port;

		private ConnectThread(String IP, int Port) {
			this.IP = IP;
			this.Port = Port;
		}

		@Override
		public void run() {
			/** 获取Socket */
			try {
				socket = new Socket();
				SocketAddress remoteAddr = new InetSocketAddress(this.IP,
						this.Port);
				socket.connect(remoteAddr, 5000);
				// 作用：每隔一段时间检查服务器是否处于活动状态，如果服务器端长时间没响应，自动关闭客户端socket
				// 防止服务器端无效时，客户端长时间处于连接状态
				socket.setKeepAlive(true);
				if (socket != null) {
					if (socket.isConnected()) {
						mOutputStream = socket.getOutputStream();
						mInputStream = socket.getInputStream();
						in = new BufferedReader(new InputStreamReader(
								mInputStream, bm));
						out = new PrintWriter(new BufferedWriter(
								new OutputStreamWriter(mOutputStream, bm)),
								true);
						/** 串口开启成功 */
						socketBack.onResult(CODE_OPEN_SUCCESS, null, null);
						/** 开启读数据等待 */
						mReadThread = new ReadThread();
						mReadThread.start();
					} else {
						socket = null;
						socketBack.onResult(CODE_ERROR, null, NormalUtils
								.getString(R.string.socket_open_error));
					}
				} else {
					socketBack.onResult(CODE_ERROR, null,
							NormalUtils.getString(R.string.socket_open_error));
				}
			} catch (Exception e) {
				socket = null;
				socketBack.onResult(CODE_ERROR, null,
						NormalUtils.getString(R.string.socket_open_error));
			}
		}
	}

	/** 判断连接是否正常 */
	private class ConnectStatus implements Runnable {
		@Override
		public void run() {
			try {
				socket.sendUrgentData(0xFF);
			} catch (Exception ex) {
				socketBack.onResult(CODE_ERROR, null,
						NormalUtils.getString(R.string.send_message_error));
				if (is_run) {
					/** 先断开 */
					closeSocket();
					/** 重新连接 */
					openSocket(IP, Port);
				}
			}
		}
	}

	/** 读数据线程 */
	/** 读数据线程 */
	private class ReadThread extends Thread {
		@Override
		public void run() {
			super.run();
			/** 定义一个包的最大长度 */
			int maxLength = 2048;
			byte[] buffer = new byte[maxLength];
			/** 每次收到实际长度 */
			int available = 0;
			/** 当前已经收到包的总长度 */
			int currentLength = 0;
			timer = new MyTimeThread();
			ThreadPoolUtils.execute(timer);
			while (!isInterrupted()) {
				try {
					available = mInputStream.available();
					if (available > 0) {
						/** 防止超出数组最大长度导致溢出 */
						if (available > maxLength - currentLength) {
							available = 0;
							currentLength = 0;
						}
						mInputStream.read(buffer, currentLength, available);
						currentLength += available;
						timer.count = 0;
					}

					if (buffer[0] != 1) {
						currentLength = 0;
					}
					if ((buffer[0] == 1) && (currentLength >= 5)
							&& (timer.count > 10)) {
						/** 转换为字符串 */
						String responseInfo = new String(buffer);
						socketBack.onResult(CODE_RECEIVE_DATA_SUCCESS,
								responseInfo, null);
						available = 0;
						currentLength = 0;
					}
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
		}
	}

	/** 倒计时线程 */
	class MyTimeThread implements Runnable {
		public int count;

		public MyTimeThread() {
			count = 0;
		}

		@Override
		public void run() {
			boolean interrupt = false;
			do {
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
					interrupt = true;
				}
				if (count < 1000)
					count++;
			} while (interrupt);
		}
	}

	/** 将16进制byte[]转化为相应字符串 */
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder();
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

}
